package com.qili.service;

import cn.hutool.core.util.IdUtil;
import com.qili.base.entity.CurrentUser;
import com.qili.entity.affaircase.AffairCase;
import com.qili.entity.affaircase.AffairRecord;
import com.qili.entity.affaircase.dto.AffairRecordDTO;
import com.qili.entity.supervisor.SupervisorFile;
import com.qili.entity.sys.SysRole;
import com.qili.entity.sys.SysRoleUser;
import com.qili.service.affairCase.AffairCaseService;
import com.qili.service.affairCase.AffairRecordService;
import com.qili.service.supervisor.SupervisorFileService;
import com.qili.service.sys.RoleUserService;
import com.qili.service.sys.impl.RoleServiceImpl;
import com.qili.util.DateUtil;
import org.activiti.engine.*;
import org.activiti.engine.repository.Deployment;
import org.activiti.engine.runtime.ProcessInstance;
import org.activiti.engine.task.Task;
import org.activiti.spring.ProcessEngineFactoryBean;
import org.apache.shiro.SecurityUtils;
import org.apache.shiro.subject.Subject;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import javax.persistence.Column;
import javax.persistence.Id;
import java.io.InputStream;
import java.text.SimpleDateFormat;
import java.util.*;

/**
 * @author zhaoyongke
 * @date 2020/11/10
 * @description
 */
@Service
public class WorkflowService {


    @Autowired
    UserLeaveService leaveService;

    @Autowired
    RuntimeService runtimeService;

    @Autowired
    TaskService taskService;

    @Autowired
    IdentityService identityService;

    @Autowired
    RepositoryService repositoryService;

    @Autowired
    ProcessEngineFactoryBean processEngine;

    @Autowired
    ProcessEngineConfiguration processEngineConfiguration;

    @Autowired
    RoleUserService roleUserService;

    @Autowired
    RoleServiceImpl roleservice;

    @Autowired
    AffairCaseService affairCaseService;

    @Autowired
    AffairRecordService affairRecordService;

    @Autowired
    SupervisorFileService supervisorFileService;


    private static final HashMap<String, Object> EMPTY_MAP = new HashMap<String, Object>(0);
    public static String JLNBSP = "JLNBSP001";// 监理内部审批
    public static String JLNBSH = "JLNBSH001";// 监理内部审核
    public static String JLJFLQ = "JLJFLQ001";// 监发两签
    public static String JLJFSQ = "JLJFSQ001";// 监发三签
    public static String JLCFSQ = "JLCFSQ001";// 承发三签
    public static String DEPTCHECK = "DEPTCHECK";// 部门审核

    public static String ZXNBSH = "ZXNBSH001";// 咨询部门审核
    public static String ZXNBSP = "ZXNBSP001";// 咨询部门审批

    public static String ZXZFLQ001 = "ZXZFLQ001";// 咨发两签


    public static String JCNBSH = "JCNBSH001";// 检测审核
    public static String JCNBSP = "JCNBSP001";// 咨询审批

    public static String JCJFLQ001 = "JCJFLQ001";// 咨发两签





    // 监理业务
    public static String JLTYPE = "001";
    public static String ZXTYPE = "003";
    public static String JCTYPE = "004";

    public static String LCTYPE001 = "001";

    //流程类型 内部审核流程
    public static String LCTYPE002 = "002";

    //流程类型 监发两签
    public static String LCTYPE003 = "003";

    //流程类型 监发三签
    public static String LCTYPE004 = "004";

    //流程类型 承发三签
    public static String LCTYPE005 = "005";
    //流程类型 部门审核
    public static String LCTYPE006 = "006";
    //流程类型 咨询部门审核
    public static String LCTYPE010 = "010";
    //流程类型 咨询内部审核
    public static String LCTYPE011 = "011";

    //流程类型 咨询内部审批
    public static String LCTYPE012 = "012";

    //流程类型 咨发两签
    public static String LCTYPE013 = "013";
    //流程类型 检发两签
    public static String LCTYPE014 = "014";

    //流程类型  检测审核
    public static String LCTYPE015 = "015";

    //流程类型  检测审批
    public static String LCTYPE016 = "016";

    //流程类型  检测部门审核
    public static String LCTYPE017 = "017";



    /**
     * 流程定义部署，相同流程定义（按照KEY判断）将覆盖上一个版本的定义
     *
     * @param name        流程定义名称（文件名)
     * @param inputStream 流程定义内容
     * @return 流程定义编号
     */
    public Deployment deploy(String name, InputStream inputStream) {
        Deployment deployment = repositoryService.createDeployment()
                .addInputStream(name, inputStream).deploy();
        return deployment;
    }

    /**
     * @param rolename
     * @Author:zhaoyongke
     * @Description:根据角色查询人员
     * @Date:16:52 2020/11/11
     */
    public String getCandidateUsersByRoleName(String rolename) {
        SysRole sysRole = new SysRole();
        sysRole.setRoleName(rolename);
        sysRole = roleservice.selectOne(sysRole);
        SysRoleUser SysRoleUser = new SysRoleUser();
        SysRoleUser.setRoleId(sysRole.getId());
        List<SysRoleUser> listroleuser = roleUserService.select(SysRoleUser);
        StringBuffer checkusers = new StringBuffer();
        for (int i = 0; i < listroleuser.size(); i++) {
            if (i == 0) {
                checkusers.append(listroleuser.get(i).getUserId());
            } else {
                checkusers.append("," + listroleuser.get(i).getUserId());
            }
        }
        return checkusers + "";
    }

    /**
     * @param userId
     * @Author:zhaoyongke
     * @Description: 通过userId获取角色SysRoleUser
     * @Date:11:57 2020/12/8
     */
    public SysRole getSysRoleByUserId(String userId) {
        SysRoleUser sysRoleUser = new SysRoleUser();
        sysRoleUser.setUserId(userId);
        List<SysRoleUser> sysRoleUserList = roleUserService.selectByCondition(sysRoleUser);
        if (sysRoleUserList.size() > 0) {
            sysRoleUser = sysRoleUserList.get(0);
        }
        String roleId = sysRoleUser.getRoleId();
        SysRole role = new SysRole();
        role.setId(roleId);
        role = roleservice.selectByPrimaryKey(role);
        return role;

    }

    /**
     * @param caseName
     * @param key
     * @param acceptType
     * @param variables
     * @Author:Zhangshuo
     * @Description:
     * @Date:13:31 2020/11/14
     */
    public String startAffairWorkflow(String caseName, String key, SupervisorFile file, String acceptType, String lcType, Map<String, Object> variables) {
        //(1)启动流程的时候统一保存到Affircase 表中一条数据
        AffairCase ace = saveAffirCase(caseName, file.getId(), acceptType, lcType, key);
        //(2)启动工作流
        String processInstanceId = startWorkflow(key, ace.getCaseId().toString(), variables);
        //(3)保存流程记录表
        AffairRecordDTO dto = new AffairRecordDTO();
        //业务表主键
        dto.setYwId(ace.getCaseId());
        //业务类型 001 监理系统 002 咨询 003 检测
        dto.setYwType(acceptType);
        //环节名称
        dto.setHjName("提交");
        //审核状态 1 提交 2 审核通过 3 审核不通过
        dto.setCheckStatus("1");
        dto.setProcessInstanceId(processInstanceId);
        String recordId=addAffairCaseRecord(dto);
        // 4）更新AffairCase 流程实例id
        ace.setProcessInstanceId(processInstanceId);
        // 当前环节record
        ace.setCurrRecordId(recordId);
        affairCaseService.updateByPrimaryKey(ace);
        //(5)修改文件表 流程状态为进行中
        //流程状态0 内部未发起流程1 内部进行中 2 内部流程审核通过3内部流程审核不通过4外部流程进行中5外部流程审核通过（归档）6 外部流程审核不通过
        if(ace.getLcType().equals("001")||ace.getLcType().equals("002") ||ace.getLcType().equals("006") ||ace.getLcType().equals("010")||ace.getLcType().equals("011")||ace.getLcType().equals("012")||ace.getLcType().equals("015")||ace.getLcType().equals("016")||ace.getLcType().equals("017")){
            file.setLcStatus("1");// 内部流程启动
        }else{
            file.setLcStatus("4");// 外部流程启动
        }

        supervisorFileService.updateByPrimaryKey(file);
        return processInstanceId;
    }


    public String startAffairWorkflowGx(String caseName, String key,String bussId ,String acceptType, String lcType, Map<String, Object> variables) {
        //(1)启动流程的时候统一保存到Affircase 表中一条数据
        AffairCase ace = saveAffirCase(caseName, bussId, acceptType, lcType, key);
        //(2)启动工作流
        String processInstanceId = startWorkflow(key, ace.getCaseId().toString(), variables);
        //(3)保存流程记录表
        AffairRecordDTO dto = new AffairRecordDTO();
        //业务表主键
        dto.setYwId(ace.getCaseId());
        //业务类型 001 监理系统 002 咨询 003 检测
        dto.setYwType(acceptType);
        //环节名称
        dto.setHjName("提交");
        //审核状态 1 提交 2 审核通过 3 审核不通过
        dto.setCheckStatus("1");
        dto.setProcessInstanceId(processInstanceId);
        String recordId=addAffairCaseRecord(dto);
        // 4）更新AffairCase 流程实例id
        ace.setProcessInstanceId(processInstanceId);
        // 当前环节record
        ace.setCurrRecordId(recordId);
        affairCaseService.updateByPrimaryKey(ace);
        return processInstanceId;
    }

    /**
     * @param caseName
     * @param businessId
     * @param acceptType
     * @Author:zhaoyongke
     * @Description: 保存到AffirCase
     * @Date:14:38 2020/12/7
     */
    public AffairCase saveAffirCase(String caseName, String businessId, String acceptType, String lcType, String key) {
        Subject sub = SecurityUtils.getSubject();
        CurrentUser currentUser = (CurrentUser) sub.getPrincipal();
        String userid = currentUser.getId();
        AffairCase ace = new AffairCase();
        //事项编码
        ace.setAffairCode(key);
        //业务表id
        ace.setBusinessId(businessId);
        //申报对象id
        ace.setApplicantId(userid);
        /*   ace.setAcceptorId(userid);*/
        //申报对象类型
        /* ace.setApplicanttype(nodeTypeId.toString());*/
        //申报对象名称
        ace.setApplicantName(currentUser.getUsername());
        //受理时间
        ace.setAcceptTime(DateUtil.formatDate(new Date()));
        //申报对象 业务类型001 监理业务 002供需业务
        ace.setApplicantType(acceptType);
        //流程类型 监发三签等
        ace.setLcType(lcType);
        ace.setValid("1");//有效标记
        //是否结束 0 未结束 1 已结束
        ace.setEndresult("0");
        //具体名称 项目名称+文件名称
        ace.setCaseName(caseName);
        ace.setCaseId(IdUtil.simpleUUID());
        affairCaseService.insert(ace);
        return ace;
    }

    public String  addAffairCaseRecord(AffairRecordDTO dto) {
        Subject sub = SecurityUtils.getSubject();
        CurrentUser currentUser = (CurrentUser) sub.getPrincipal();
        String userid = currentUser.getId();
        AffairRecord affairRecord = new AffairRecord();
        affairRecord.setRecordId(IdUtil.simpleUUID());
        //业务表主键
        affairRecord.setYwId(dto.getYwId());
        /**
         * 业务类型 001 监理系统 002 咨询 003 检测
         */
        affairRecord.setYwType(dto.getYwType());
        //环节名称
        affairRecord.setHjName(dto.getHjName());
        //审核状态 1 提交 2 审核通过 3 审核不通过
        affairRecord.setCheckStatus(dto.getCheckStatus());
        //备注
        affairRecord.setRemark(dto.getRemark());
        //操作人
        affairRecord.setOperUserId(userid);
        //操作时间
        affairRecord.setOperDate(DateUtil.formatDate(new Date()));
        // 任务id
        affairRecord.setTaskId(dto.getTaskId());
        // 工作流实例id
        affairRecord.setProcessInstanceId(dto.getProcessInstanceId());

        affairRecordService.insert(affairRecord);
        return affairRecord.getRecordId();
    }

    public String  addAffairCaseRecordApp(AffairRecordDTO dto,String userId) {
        String userid = userId;
        AffairRecord affairRecord = new AffairRecord();
        affairRecord.setRecordId(IdUtil.simpleUUID());
        //业务表主键
        affairRecord.setYwId(dto.getYwId());
        /**
         * 业务类型 001 监理系统 002 咨询 003 检测
         */
        affairRecord.setYwType(dto.getYwType());
        //环节名称
        affairRecord.setHjName(dto.getHjName());
        //审核状态 1 提交 2 审核通过 3 审核不通过
        affairRecord.setCheckStatus(dto.getCheckStatus());
        //备注
        affairRecord.setRemark(dto.getRemark());
        //操作人
        affairRecord.setOperUserId(userid);
        //操作时间
        affairRecord.setOperDate(DateUtil.formatDate(new Date()));
        // 任务id
        affairRecord.setTaskId(dto.getTaskId());
        // 工作流实例id
        affairRecord.setProcessInstanceId(dto.getProcessInstanceId());

        affairRecordService.insert(affairRecord);
        return affairRecord.getRecordId();
    }

    /**
     * @param key
     * @param caseId
     * @param variables
     * @Author:zhaoyongke
     * @Description: 启动工作流
     * @Date:15:11 2020/12/7
     */
    public String startWorkflow(String key, String caseId, Map<String, Object> variables) {
        ProcessInstance processInstance = runtimeService.startProcessInstanceByKey(key, caseId, variables);
        return processInstance.getId();
    }

    /**
     * @param taskId
     * @param append
     * @param variables
     * @Author:zhaoyongke
     * @Description: 完成任务
     * @Date:15:46 2020/11/12
     */
    public void completeTask(String taskId, boolean append, Map<String, Object> variables) {
        Task task = taskService.createTaskQuery().taskId(taskId).singleResult();
    /*    if (task == null) {
            throw new TaskException("任务提交失败[" + taskId + "]");
        }*/

        if (variables == null || variables.isEmpty()) {
            if (append) {
                taskService.complete(taskId);
            } else {
                taskService.complete(taskId, EMPTY_MAP);
            }
        } else {
            if (append) {
                Map<String, Object> newVariables = taskService.getVariables(taskId);
                newVariables.putAll(variables);
                taskService.complete(taskId, newVariables);
            } else {
                taskService.complete(taskId, variables);
            }

        }
    }


}
